#include "ray.hh"

Ray::Ray (Vector3f point)
  : p_ (point)
{
  for (int i = 0; i < 3; ++i)
    u_ (i, 0);
}

Ray::~Ray ()
{}

void
Ray::set_line (Vector3f& point)
{
  p2_ = point;
  u_ = point - p_;
}

bool
Ray::intersect (const Vector3f& pos, const BoundingSphere* s)
{
  Vector3f b = p_ + u_;
  Vector3f a = p_;
  Vector3f c = pos;
  float radius = s->radius ();

  float alpha = (b (0) - a (0)) * (b (0) - a (0))
    + (b (1) - a (1)) * (b (1) - a (1))
    + (b (2) - a (2)) * (b (2) - a (2));

  float beta = 2 * ((b (0) - a (0)) * (a (0) - c (2))
  		    + (b (1) - a (1)) * (a (1) - c (1))
  		    + (b (2) - a (2)) * (a (2) - c (0)));
  float gamma = a (0) * a (0) + a (1) * a (1) + a (2) * a (2)
    + c (2) * c (2) + c (1) * c (1) + c (0) * c (0)
    - 2 * (a (0) * c (2) + a (1) * c (1) + a (2) * c (0))
    - radius * radius;

  float delta = beta * beta - 4 * alpha * gamma;

  return (delta >= 0);
}

bool
Ray::intersect (const Vector3f& pos, const BoundingBox* s)
{
  (void) pos;
  (void) s;
  std::cout << "WARNING: unhandled intersection between ray and cube ATM" << std::endl;
  return false;
}

Vector3f*
Ray::intersect (Plane* p)
{
  float a = p->a ();
  float b = p->b ();
  float c = p->c ();
  float d = p->d ();

  float t = - (a * p_ (0) + b * p_ (1) + c * p_ (2) + d) / (a * u_ (0) + b * u_ (1) + c * u_ (2));

  Vector3f* res = new Vector3f ();

  for (int i = 0; i < 3; ++i)
    (*res) (i, p_ (i) + t * u_ (i));

  return res;
}
